const { ethers } = require("hardhat");
const fs = require("fs");
const path = require("path");

async function main() {
    console.log("🔄 开始升级代理合约（健壮版本）...\n");

    const [deployer] = await ethers.getSigners();
    console.log(`📝 操作者地址: ${deployer.address}`);

    // 从部署记录文件读取代理合约地址
    const deploymentFile = path.join(__dirname, 'deployment.json');
    let PROXY_ADDRESS;

    try {
        if (fs.existsSync(deploymentFile)) {
            const deployment = JSON.parse(fs.readFileSync(deploymentFile, 'utf8'));
            PROXY_ADDRESS = deployment.proxy;
            console.log(`📋 代理合约地址: ${PROXY_ADDRESS}`);
        } else {
            console.log("❌ 未找到部署记录文件");
            return;
        }
    } catch (error) {
        console.log("❌ 读取部署记录失败:", error.message);
        return;
    }

    // 检查合约代码
    const code = await ethers.provider.getCode(PROXY_ADDRESS);
    if (code === '0x') {
        console.log("❌ 代理合约没有代码，请重新部署");
        return;
    }

    // 部署逻辑合约 V2
    console.log("\n📦 部署 LogicContractV2...");
    const LogicContractV2 = await ethers.getContractFactory("LogicContractV2");
    const logicV2 = await LogicContractV2.deploy();
    await logicV2.waitForDeployment();
    const logicV2Address = await logicV2.getAddress();
    console.log(`✅ LogicContractV2 部署成功: ${logicV2Address}`);

    // 使用最小 ABI 连接到代理合约
    console.log(`\n🔗 连接到代理合约...`);
    const proxyABI = [
        "function upgrade(address newImplementation) external",
        "function implementation() external view returns (address)",
        "function admin() external view returns (address)"
    ];

    const proxy = new ethers.Contract(PROXY_ADDRESS, proxyABI, deployer);

    // 检查当前管理员
    try {
        const admin = await proxy.admin();
        console.log(`📋 当前管理员: ${admin}`);
        console.log(`📋 当前操作者: ${deployer.address}`);

        if (admin.toLowerCase() !== deployer.address.toLowerCase()) {
            console.log("❌ 操作者不是管理员，无法升级");
            return;
        }
    } catch (error) {
        console.log("❌ 检查管理员失败:", error.message);
        // 继续尝试升级，可能 ABI 不匹配但升级函数仍然有效
    }

    // 尝试升级
    console.log("\n⬆️  尝试升级到 V2...");
    try {
        const upgradeTx = await proxy.upgrade(logicV2Address);
        const receipt = await upgradeTx.wait();
        console.log("✅ 升级交易成功，区块:", receipt.blockNumber);
    } catch (error) {
        console.log("❌ 升级失败:", error.message);
        return;
    }

    // 验证升级
    console.log("\n🔍 验证升级结果...");
    try {
        const newImpl = await proxy.implementation();
        console.log(`✅ 新实现合约地址: ${newImpl}`);

        if (newImpl.toLowerCase() === logicV2Address.toLowerCase()) {
            console.log("🎉 升级验证成功！");
        } else {
            console.log("⚠️  实现地址不匹配，但升级交易成功");
        }
    } catch (error) {
        console.log("⚠️  无法读取新实现地址，但升级交易可能已成功:", error.message);
    }

    // 测试新功能
    console.log("\n🧪 测试 V2 新功能...");
    const logicV2ABI = [
        "function initialize() external",
        "function setNumber(uint256) external",
        "function getNumber() external view returns (uint256)",
        "function setMessage(string) external",
        "function message() external view returns (string)",
        "function multiplyNumber(uint256) external",
        "function version() external view returns (string)"
    ];

    const proxyAsV2 = new ethers.Contract(PROXY_ADDRESS, logicV2ABI, deployer);

    try {
        // 初始化 V2
        console.log("🔧 初始化 V2 合约...");
        const initTx = await proxyAsV2.initialize();
        await initTx.wait();
        console.log("✅ V2 合约初始化成功");

        // 测试新功能
        const setMessageTx = await proxyAsV2.setMessage("Hello from Robust Upgrade!");
        await setMessageTx.wait();
        console.log("✅ 设置消息成功");

        const message = await proxyAsV2.message();
        console.log(`✅ 消息内容: ${message}`);

        const version = await proxyAsV2.version();
        console.log(`✅ 合约版本: ${version}`);

        console.log("\n🎉 升级和测试完成！");
    } catch (error) {
        console.log("❌ 测试新功能失败:", error.message);
    }
}

main()
    .then(() => process.exit(0))
    .catch((error) => {
        console.error("❌ 升级失败:", error);
        process.exit(1);
    });